#include "EntityManager.hpp"

#include "Exception.hpp"

#include "Block.hpp"
#include "Entity.hpp"
#include "MoveableEntity.hpp"
#include "CollisionModel.hpp"


void EntityManager::clearEntities()
{
	std::list<Entity*>::iterator iter;
	
	for (iter = entities.begin(); iter != entities.end(); iter++)
	{	
		//free all memory
		delete *iter;
	}
	//remove all entities from list
	entities.clear();
}


void EntityManager::renderEntities()
{
	std::list<Entity*>::iterator iter;
	
	for(iter=entities.begin(); iter!=entities.end(); iter++)
	{
		(*iter)->Render();
	}
}


void EntityManager::renderWithoutEntity(Entity* entityPtr)
{
	std::list<Entity*>::iterator iter;
	
	for (iter = entities.begin(); iter != entities.end(); iter++)
	{
		if (*iter != entityPtr)
		{	
		 	(*iter)->Render();
		}
	}
}

void EntityManager::renderCollisionModels()
{
	for(Entity* ent : entities)
	{
		ent->cm.Render(ent->position);
	}
}





void EntityManager::onInput(InputStruct Input)
{
	for(Entity* ent : entities)
	{
		ent->onInput(Input);
	}
}


void EntityManager::setEntities(std::list<Entity*> e)
{
	entities = e;
}


void EntityManager::markToRemove(Entity* entityPtr)
{
	entityPtr->Delete();
	entitiesToRemove.push_back(entityPtr);
}


void EntityManager::removeEntities()
{
	std::list<Entity*>::iterator iter;
	
	for (iter = entitiesToRemove.begin(); iter != entitiesToRemove.end(); iter++)
	{
		delete *iter;
		entities.remove(*iter);
	}
}


bool EntityManager::addEntity(Entity* entityPtr, bool CheckCollision)
{
	//check if there is enough room:
	if(CheckCollision)
	{
		for(Entity* ent : entities)
		{
			if(ent!=entityPtr)
			{
				if( (!ent->IsDeleted()) && //do not collide with this entity if it will be deleted soon
					CollisionModel::CheckCollision(	entityPtr->cm,	entityPtr->position,
													ent->cm,		ent->position))
				{
					delete entityPtr;	
					return false;
				}
			}
		}
	}


	//we push at front so that objects that are created in onTick() won't be moved in the same round.
	entities.push_front(entityPtr);

	return true;
}


void EntityManager::onTick(float time)
{
	removeEntities();
	entitiesToRemove.clear();

	std::list<Entity*>::iterator iter;
	
	for (iter = entities.begin(); iter != entities.end(); iter++)
	{
		(*iter)->onTick(time);
	}
}
	

void EntityManager::MoveEntity(MoveableEntity* theEntity, float Time)
{
	for(Entity* ent : entities)
	{
		if(ent!=theEntity)
		{
			if(CollisionModel::CheckCollision(	theEntity->cm,	theEntity->position+theEntity->velocity*Time,
												ent->cm,		ent->position))
			{
				Vector3f res=CollisionModel::CollisionNormal(	theEntity->cm,	theEntity->position, theEntity->velocity*Time,
																ent->cm,		ent->position);
				if(res.x!=0)
					theEntity->velocity.x*=-1;
				else if(res.y!=0)
					theEntity->velocity.y*=-1;
				//the objects stuck together, but there is nothing, that we coul do :(
				/*else
					THROW(Exception() << ex_message("wrong collision normal!"));*/

				ent->onTouch(theEntity);

				return;
			}
		}
	}
	theEntity->position+=theEntity->velocity*Time;
}
